package xyz.cerberu.cet.spider.resource.spider;

import com.spider.core.SpiderClient;
import com.spider.core.SpiderConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import xyz.cerberu.cet.anime.dao.AnimeDao;
import xyz.cerberu.cet.anime.domain.Anime;
import xyz.cerberu.cet.global.domain.Global;
import xyz.cerberu.cet.global.utils.PropertiesUtils;
import xyz.cerberu.cet.global.utils.TimeUtils;
import xyz.cerberu.cet.spider.resource.spider.Logic.ResourceLogic;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Date;
import java.time.*;
import java.util.*;

/**
 * @author β世界
 * Created on 15:44
 * @Description 资源的爬取对象
 * 所有的爬虫爬取完毕，都需要获取当前爬虫所有的爬取内容(可以通过getResultItem()方法来获取存储在这个client中的所有信息)
 * 获取这些信息进行统计数量，还有未处理的链接，然后通过日志文件和数据库记录此处爬取
 */
@Component
public class ResourceSpider {
    private final static Logger logger = LoggerFactory.getLogger(ResourceSpider.class);
    private final Global global;
    private final AnimeDao animeDao;
    /** 不能自动注入，需要根据不同的用处使用不同的设置 **/
    private final SpiderConfig resourceSpiderConfig;
    private final ResourceLogic resourceLogic;
    private final RedisTemplate<String, Object> redisTemplate;
    private static final String PREFIX_URL = "https://www.dmhy.org/topics/list?keyword=";
    private static final String TODAY_UPDATE_URL = "https://www.dmhy.org/topics/list/recent/1+day?sort_id=2&team_id=0&order=date-desc";

    @Autowired
    public ResourceSpider(Global global, AnimeDao animeDao, SpiderConfig resourceSpiderConfig, ResourceLogic resourceLogic, RedisTemplate<String, Object> redisTemplate) {
        this.global = global;
        this.animeDao = animeDao;
        this.resourceSpiderConfig = resourceSpiderConfig;
        this.resourceLogic = resourceLogic;
        this.redisTemplate = redisTemplate;
    }

    /**
     * @author β世界 on 17:19 2020/4/12
     * 更新这个季度的动漫
     **/
    @Scheduled(cron = "0 0 0/12 * * ?") // 每12小时执行一次
    public void quarterUpdateAnime() {
        try{
            SpiderClient client = resourceSpiderConfig.create();
            client.addProcessLogic(resourceLogic);

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(System.currentTimeMillis()));
            // 计算季度
            String quarter = TimeUtils.calculateQuarter((calendar.get(Calendar.MONTH)+1));

            // 获取动漫
            List<Anime> animeList = animeDao.selectAnimeByDate(calendar.getWeekYear(),quarter,0);
            for (Anime anime : animeList) {
                if(anime == null){continue;}
                client.addSeedUrl(PREFIX_URL + anime.getAnime_url() + "&sort_id=2&team_id=0&order=date-desc");
                if(anime.getAlias() != null){
                    client.addSeedUrl(PREFIX_URL + URLEncoder.encode(anime.getAlias(),"UTF-8") + "&sort_id=2&team_id=0&order=date-desc");
                }
            }

            client.start(); // 爬取开始
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
    }

    /**
     * @author β世界 on 21:13 2020/4/12
     * 获取当前周会更新的动漫，范围是这个月和前三个月中所有的动漫(防止有些动漫的集数过多，导致更新不完整)
     **/
    @Scheduled(cron = "0 10 0/1 * * ?") // 每1小时执行一次
    public void updateTodayAnimeResource() {
        try {
            SpiderClient client = resourceSpiderConfig.create();
            // 设置处理逻辑
            client.addProcessLogic(resourceLogic);
            
            // 获取当前的日期
            LocalDate now = LocalDate.now();
            // 计算出四个月的时间
            Date start = new Date(now.minusMonths(4).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli());
            Date end = new Date(now.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli());
            // 计算周期
            int week = DayOfWeek.from(now.getDayOfWeek()).getValue();

            // 获取动漫
            List<Anime> animeList = animeDao.selectRangeAnimeByWeek(start,end, week);
            animeList.addAll(getSpecialAnime(week));
            for (Anime anime : animeList) {
                if(anime == null){
                    continue;
                }
                // 动漫的url编码不能是空
                if(!"".equals(anime.getAnime_url().trim())){
                    client.addSeedUrl(PREFIX_URL + anime.getAnime_url() + "&sort_id=2&team_id=0&order=date-desc");
                }
                // 别名不能空字符串
                if(anime.getAlias() != null && !"".equals(anime.getAlias())){
                    client.addSeedUrl(PREFIX_URL + URLEncoder.encode(anime.getAlias(),"UTF-8") + "&sort_id=2&team_id=0&order=date-desc");
                }
            }

            client.start(); // 爬取开始
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author β世界 on 19:20 2020/4/25
     * @Description 获取最近动漫花园的资源更新情况
     **/
    @Scheduled(cron = "0 0 0/1 * * ?") // 每1小时执行一次
    public void todayUpdateResource(){
        SpiderClient client = resourceSpiderConfig.create();
        // 设置处理逻辑
        client.addProcessLogic(resourceLogic);

        // 今日更新
        client.addSeedUrl(TODAY_UPDATE_URL);

        client.start(); // 爬取开始
    }

    /**
     * @author β世界 on 8:22 2020/6/24
     * 更新指定的动漫资源,用于手动更新
     * @param animeList: 动漫内容
     **/
    @SuppressWarnings("unused")
    public void updateResourceByAnime(List<Anime> animeList) {
        try {

            SpiderClient client = resourceSpiderConfig.create();
            // 设置处理逻辑
            client.addProcessLogic(resourceLogic);

            for(Anime anime : animeList){
                // 今日更新
                client.addSeedUrl(PREFIX_URL + anime.getAnime_url() + "&sort_id=2&team_id=0&order=date-desc");
                if(anime.getAlias() != null && !"".equals(anime.getAlias())){
                    client.addSeedUrl(PREFIX_URL + URLEncoder.encode(anime.getAlias(),"UTF-8") + "&sort_id=2&team_id=0&order=date-desc");
                }
            }

            // 爬取开始
            client.start();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author β世界 on 21:16 2020/7/1
     * 将redis的过期资源进行清除
     **/
    @Deprecated
    public void updatePastResource(){
        Long removeNumber = 0L;
        // 获取所有的字幕组
        Set<String> subtitle =  redisTemplate.keys("subtitle-*");
        long endTime = LocalDateTime.now().minusDays(3).toEpochSecond(ZoneOffset.of("+8"));
        // 遍历每个字幕组，并且删除已经存在时间已经超过三天的更新条目
        for (String s : subtitle) {
            removeNumber += redisTemplate.opsForZSet().removeRangeByScore(s, 0L, endTime);
        }
        logger.info("清除Redis中过期的资源条目数量:"+removeNumber);
    }

    /**
     * @author β世界 on 14:17 2020/4/30
     * @Description 获取特殊更新的动漫
     **/
    public List<Anime> getSpecialAnime(int week){
        List<Anime> animeList = new ArrayList<>();
        if(global.getSpecialAnime() != null && global.getSpecialAnime().isFile()){
            // 读取特殊更新的动漫文件
            Properties properties = PropertiesUtils.getProperties(global.getSpecialAnime());
            String weekInfo = properties.getProperty(String.valueOf(week));
            // 用逗号分开每个ani_id
            String[] aniIds = weekInfo.split(" ,");
            for (String aniId : aniIds){
                animeList.add(animeDao.selectAnimeByID(aniId));
            }
        }
        return animeList;
    }

}
